package com.zhuiYun.project.api.dukaqi;

import com.sun.jna.Library;
import com.sun.jna.Native;

interface CLibrary extends Library {
    //DLL绝对路径的地址获取，注意要去空格，特别坑
    //不同版本的读写器，接口DLL文件名称、函数名称是一样的,但内核代码不一样，请选用与读写器、操作系统一致的OUR_IDR.dll
    String filePath = CLibrary.class.getResource("").getPath().replaceFirst("/","").replaceAll("%20"," ")+"OUR_IDR";
    CLibrary sdtapi = (CLibrary) Native.loadLibrary(filePath, CLibrary.class);

    //动态链接库中的方法
    byte idr_beep(int xms);                         //让设备发出声音
    byte pcdgetdevicenumber(byte[] devicenumber);   //读取设备编号
    String pcdgetdevicenumber_str();                //读取设备编号,输出字符串
    byte idr_read(byte[] mypiccserial );            //轻松读卡,只要卡在感应区，每次执行此方法都可以读到卡号
    byte idr_read_once(byte[] mypiccserial );       //卡在感应区时只能读一次,需将卡从感应区盒开再放入感应区才能再次读到卡
    String idr_read_8h10d_str();                    //读卡，输出十位十进制卡号
    String idr_read_once_8h10d_str();               //读卡，输出十位十进制卡号,卡在感应区时只读一次
}
public class IDReader {
    public static String aa(String aa){
        System.out.println("+++++++++++++++++"+aa);
        return aa;
    }
    public static String  main(String[] args) {
//        System.getProperty("java.library.path");
//        String filePath = CLibrary.class.getResource("").getPath().replaceFirst("/", "").replaceAll("%20", " ") + "OUR_IDR.DLL";
//        System.out.println("本示例引用的DLL文件：" + filePath);

        if (args.length == 0) {
            System.out.println("\n请先输入运行参数！");
            System.out.println("\n参数 0：驱动读卡器嘀一声");
            System.out.println("\n参数 1：读取设备编号");
            System.out.println("\n参数 2：读取设备编号,输出字符串");
            System.out.println("\n参数 3：轻松读卡");
            System.out.println("\n参数 4：轻松读卡，卡在感应区时只能读一次,需将卡从感应区盒开再放入感应区才能再次读到卡");
            System.out.println("\n参数 5：轻松读卡，输出十位十进制卡号");
            System.out.println("\n参数 6：轻松读卡，输出十位十进制卡号，卡在感应区时只能读一次");
            return "\n请先输入运行参数！" +
                    "\n参数 0：驱动读卡器嘀一声" +
                    "\n参数 1：读取设备编号" +
                    "\n参数 2：读取设备编号,输出字符串" +
                    "\n参数 3：轻松读卡" +
                    "\n参数 4：轻松读卡，卡在感应区时只能读一次,需将卡从感应区盒开再放入感应区才能再次读到卡" +
                    "\n参数 5：轻松读卡，输出十位十进制卡号" +
                    "\n参数 6：轻松读卡，输出十位十进制卡号，卡在感应区时只能读一次";
        }
        if (args[0].equals("0")) {             //驱动读卡器发嘀一声
            CLibrary.sdtapi.idr_beep(50);
            return "结果:如果能听到读卡器嘀一声表示成功，否则请检查读卡器是否已连上线！\n\n";
        } else if (args[0].equals("1"))          //读取设备编号，可做为软件加密狗用,也可以根据此编号在公司网站上查询保修期限
        {
            int status;                          //存放返回值
            byte[] devicenumber = new byte[4];   //4字节设备编号
            System.out.print("\n1-读取设备编号\n");
            status = (int) (CLibrary.sdtapi.pcdgetdevicenumber(devicenumber) & 0xff);//& 0xff用于转为无符号行数据
            System.out.print("结果:");
            if (status == 0) {
                CLibrary.sdtapi.idr_beep(38);
                return (devicenumber[0] & 0xff) + "-" + (devicenumber[1] & 0xff) + "-" + (devicenumber[2] & 0xff) + "-" + (devicenumber[3] & 0xff);
            } else {
                return PrintErrInf(status);   //错误代码提示
            }
        }else if (args[0].equals("2"))            //读取设备编号，直接输出字符串
        {
            System.out.print("\n2-读取设备编号\n");
            String statustr = CLibrary.sdtapi.pcdgetdevicenumber_str().trim();   //设备编号
            if(statustr.length()==10) {
                CLibrary.sdtapi.idr_beep(38);
                return statustr;
            }else{
                return PrintErrStr(statustr);   //错误字符串代码提示
            }
        }else if (args[0].equals("3"))            //轻松读卡
        {
            int status;                           //存放返回值
            byte[] mypiccserial  = new byte[5];   //5字节卡序列号
            System.out.print("\n3-轻松读卡\n");
            status = (int) (CLibrary.sdtapi.idr_read(mypiccserial ) & 0xff);          //只要卡在感应区，每次执行此方法都可以读到卡号
            System.out.print("结果:");
            if (status == 0) {
                CLibrary.sdtapi.idr_beep(38);
                String serialnumber = "";
                for (int i = 0; i < 5; i++) {
                    String bytestr = "00" + Integer.toHexString(mypiccserial[i] & 0xff);
                    serialnumber = serialnumber + bytestr.substring(bytestr.length() - 2, bytestr.length());
                }
                System.out.print("读取成功!16进制卡序列号为:" + serialnumber+"\n");
                long cardnum;
                cardnum=mypiccserial[4] & 0xff;
                cardnum=cardnum+(mypiccserial[3] & 0xff) *256;
                cardnum=cardnum+(mypiccserial[2] & 0xff) *65536;
                cardnum=cardnum+(mypiccserial[1] & 0xff) *16777216;
                long cardno10 = 0;
                for (int j=28; j>=0; j-=4) {
                    cardno10 = cardno10<<4 | (cardnum>>>j & 0xF);
                }
                return "换算成10进制卡号:"+String.format("%010d", cardno10)+"\n";
            } else {
                return PrintErrInf(status);//错误代码提示
            }

        }else if (args[0].equals("4"))            //轻松读卡，卡在感应区时只能读一次,需将卡从感应区盒开再放入感应区才能再次读到卡
        {
            int status;                           //存放返回值
            byte[] mypiccserial  = new byte[5];   //5字节卡序列号

            System.out.print("\n4-轻松读一次卡\n");
            status = (int) (CLibrary.sdtapi.idr_read_once(mypiccserial ) & 0xff);   //卡在感应区时只能读一次,需将卡从感应区盒开再放入感应区才能再次读到卡
            System.out.print("结果:");
            if (status == 0) {
                CLibrary.sdtapi.idr_beep(38);
                String serialnumber = "";
                for (int i = 0; i < 5; i++) {
                    String bytestr = "00" + Integer.toHexString(mypiccserial[i] & 0xff);
                    serialnumber = serialnumber + bytestr.substring(bytestr.length() - 2, bytestr.length());
                }
                System.out.print("读取成功!16进制卡序列号为:" + serialnumber+"\n");

                long cardnum;
                cardnum=mypiccserial[4] & 0xff;
                cardnum=cardnum+(mypiccserial[3] & 0xff) *256;
                cardnum=cardnum+(mypiccserial[2] & 0xff) *65536;
                cardnum=cardnum+(mypiccserial[1] & 0xff) *16777216;
                long cardno10 = 0;
                for (int j=28; j>=0; j-=4) {
                    cardno10 = cardno10<<4 | (cardnum>>>j & 0xF);
                }
                return String.format("%010d", cardno10);
            } else {
                return PrintErrInf(status);//错误代码提示
            }

        }else if (args[0].equals("5"))            //读卡，输出十位十进制卡号
        {
            System.out.print("\n5-读10进制卡号\n");
            String statustr = CLibrary.sdtapi.idr_read_8h10d_str().trim();        //只要卡在感应区，每次执行此方法都可以读到卡号
            if(statustr.length()==10) {
                CLibrary.sdtapi.idr_beep(30);
                return statustr;
            }else{
                //错误字符串代码提示
                return PrintErrStr(statustr);
            }
        }else if (args[0].equals("6"))            //读卡，输出十位十进制卡号，卡在感应区时只能读一次,需将卡从感应区盒开再放入感应区才能再次读到卡
        {
//            System.out.print("\n6-读10进制卡号，只读一次\n");
            String statustr = CLibrary.sdtapi.idr_read_once_8h10d_str().trim();     ////卡在感应区时只能读一次,需将卡从感应区盒开再放入感应区才能再次读到卡
            if(statustr.length()==10) {
                CLibrary.sdtapi.idr_beep(50);
                return statustr;
            }else{
                return PrintErrStr(statustr); //错误字符串代码提示
            }
        }else {
            return null;
        }

    }

    //----------------------------------------------------------------------------------错误字符串代码提示
    static String PrintErrStr(String Errstr){
        if(Errstr.equals("ER08")){
            //"错误代码：8，未寻到卡，请重新拿开卡后再放到感应区！\n"
            return null;
        } else if(Errstr.equals("ER22")){
            return "ER22";
        } else if(Errstr.equals("ER23")){
            return null;//"ER23";
        } else if(Errstr.equals("ER24")){
            return "ER24";
        }else {
            return "错误代码："+Errstr;
        }
    }

    //----------------------------------------------------------------------------------错误代码提示
    static String PrintErrInf(int errcode) {
        switch(errcode){
            case 8:
                return "错误代码：8，未寻到卡，请重新拿开卡后再放到感应区！\n";
            case 21:
                return "错误代码：21，没有动态库！\n";
            case 22:
                return "错误代码：22，动态库或驱动程序异常！\n";
            case 23:
                return "错误代码：23，驱动程序错误或尚未安装！\n";
            case 24:
                return "错误代码：24，操作超时，一般是动态库没有反映！\n";
            case 25:
                return "错误代码：25，发送字数不够！\n";
            case 26:
                return "错误代码：26，发送的CRC错！\n";
            case 27:
                return "错误代码：27，接收的字数不够！\n";
            case 28:
                return "错误代码：28，接收的CRC错！\n";
            default:
                return "未知错误，错误代码："+Integer.toString(errcode)+"\n";
        }
    }
}
